//package eee.xiang.cloud_learning.common.zookeeper;
//
//import org.apache.curator.framework.CuratorFramework;
//import org.apache.curator.framework.recipes.cache.*;
//import org.apache.curator.framework.recipes.leader.*;
//import org.apache.curator.framework.state.ConnectionState;
//import org.apache.curator.framework.state.ConnectionStateListener;
//import org.apache.curator.retry.ExponentialBackoffRetry;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//
//import java.net.InetAddress;
//import java.net.UnknownHostException;
//import java.util.Objects;
//
//import static org.apache.curator.framework.CuratorFrameworkFactory.builder;
//
///**
// * @author x-yin
// * @Date 2019/8/27
// */
//@Configuration
//public class ZKConfig {
//
//    public static final String rootPath = "/cloud";
//    public static final String masterKey = "/cloud/masterKey";
//
//    private static final Logger log = LoggerFactory.getLogger(ZKConfig.class);
//
//    @Value("${zookeeper.url}")
//    private String zkUrl;
//
//    /**
//     * Curator提供了三种类型的缓存方式：
//     * <li>
//     * Path Cache
//     * Path Cache用来监控一个ZNode的子节点. 当一个子节点增加，更新，删除时，Path Cache会改变它的状态，会包含最新的子节点， 子节点的数据和状态。
//     * </li>
//     * <li>
//     * Node Cache
//     * </li>
//     * <li>
//     * Tree Cache
//     * </li>
//     * <span>
//     * 想使用cache，必须调用它的start方法，不用之后调用close方法
//     * </span>
//     */
//    public static TreeCache treeCache;
//    public static PathChildrenCache pathChildrenCache;
//    public static LeaderLatch leaderLatch;
//    public static LeaderSelector leaderSelector;
//
//    @Bean
//    public CuratorFramework zkClient() throws Exception {
//        CuratorFramework client = builder()
//                .connectString(zkUrl)
//                .sessionTimeoutMs(60000)
//                .connectionTimeoutMs(5000)
//                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
//                .build();
//        client.start();
//
//        //监听连接
//        client.getConnectionStateListenable().addListener(new ConnectionStateListener() {
//            @Override
//            public void stateChanged(CuratorFramework client, ConnectionState newState) {
//                if (Objects.equals(newState, ConnectionState.LOST)) {
//                    log.info("连接丢失！");
//                } else if (Objects.equals(newState, ConnectionState.CONNECTED)) {
//                    log.info("新建连接！");
//                } else if (Objects.equals(newState, ConnectionState.RECONNECTED)) {
//                    log.info("重新连接！");
//                }
//            }
//        });
//
//        initLocalCache(client, rootPath);
//        initPathChildrenCache(client, rootPath);
//
//        /**
//         *  Curator两种选主方式
//         *  <li>
//         *      leaderLatch     发生故障才会释放主权
//         *  </li>
//         *  <li>
//         *      leaderSelector  执行完任务释放主权
//         *  </li>
//         */
//        initLeaderLatch(client,masterKey);
////        initLeaderSelector(client,masterKey);
//
//        return client;
//    }
//
//    /**
//     * 初始化本地缓存
//     *
//     * @param watchRootPath
//     * @throws Exception
//     */
//    private void initLocalCache(CuratorFramework client, String watchRootPath) throws Exception {
//        treeCache = new TreeCache(client, watchRootPath);
//
//        TreeCacheListener listener = (client1, event) -> {
//            log.info("event:" + event.getType() +
//                    " | path: " + (null != event.getData() ? event.getData().getPath() : null));
//
//            if (event.getData() != null && event.getData().getData() != null) {
//                log.info("发生变化的节点内容为：" + new String(event.getData().getData()));
//            }
//        };
//        treeCache.getListenable().addListener(listener);
//        treeCache.start();
//    }
//
//    public static void initPathChildrenCache(CuratorFramework client, String watchRootPath) throws Exception {
//        pathChildrenCache = new PathChildrenCache(client, watchRootPath,true);
//        pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
//            @Override
//            public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
//                switch (pathChildrenCacheEvent.getType()){
//                    case CHILD_ADDED:
//                        log.info("增加节点："+pathChildrenCacheEvent.getData().getPath()+";数据是："+ new String(pathChildrenCacheEvent.getData().getData()));
//                        break;
//                    case CHILD_REMOVED:
//                        log.info("删除节点："+pathChildrenCacheEvent.getData());
//                        break;
//                    case CHILD_UPDATED:
//                        log.info("更新节点："+new String(pathChildrenCacheEvent.getData().getData()));
//                        break;
//                        default:
//                            break;
//                }
//            }
//        });
//        pathChildrenCache.start();
//    }
//
//    public void initLeaderLatch(CuratorFramework client, String masterKey) throws Exception {
//        String id = InetAddress.getLocalHost().getHostAddress();
//        leaderLatch = new LeaderLatch(client, masterKey, id);
//        leaderLatch.addListener(new LeaderLatchListener() {
//            @Override
//            public void isLeader() {
//                log.info("客户端: {} 成为主节点！",id);
//            }
//
//            @Override
//            public void notLeader() {
//                log.info("客户端: {} 不是主节点. ",id);
//            }
//        });
//        leaderLatch.start();
//    }
//
//    public void initLeaderSelector(CuratorFramework client, String masterKey){
//        leaderSelector = new LeaderSelector(client, masterKey, new LeaderSelectorListenerAdapter() {
//            @Override
//            public void takeLeadership(CuratorFramework curatorFramework) throws Exception {
//                //todo 成为主节点进行的操作，结束后就会释放主节点
//
//            }
//        });
//        leaderSelector.autoRequeue();//确保此实例在释放领导权后还可能获得领导权。
//        leaderSelector.start();
//    }
//
//
//    public static boolean isLeader() throws Exception {
//        String id = leaderLatch.getLeader().getId();
//        log.info("主权ID：{}", id);
//        return leaderLatch.hasLeadership();
//    }
//
//
//    public static void clearCache(){
//        treeCache.close();
//    }
//}
